import { Injectable, NotFoundException } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { BookEntity } from '../../../study/book/entities/book.entity'
import { BookTagEntity } from '../../../study/book/entities/book-tag.entity'
import { MovieEntity } from '../../../study/movie/entities/movie.entity'
import { VideoTagEntity } from '../../../study/movie/entities/video-tag.entity'
import { CreateAppDto } from '../dto/create-app.dto'
import { QueryAppDto } from '../dto/query-app.dto'
import { UpdateAppDto } from '../dto/update-app.dto'
import { SettingAppIndexEntity } from '../entities/app.entity'

@Injectable()
export class AppService {
  constructor(
    @InjectRepository(SettingAppIndexEntity)
    private readonly appRepository: Repository<SettingAppIndexEntity>,
    @InjectRepository(BookTagEntity)
    private readonly bookTagRepository: Repository<BookTagEntity>,
    @InjectRepository(VideoTagEntity)
    private readonly videoTagRepository: Repository<VideoTagEntity>,
  ) { }

  /**
   * 创建首页应用
   */
  async create(createAppDto: CreateAppDto) {
    const app = this.appRepository.create({
      ...createAppDto,
      isDelete: 0,
      createdAt: new Date(),
    })
    return this.appRepository.save(app)
  }

  /**
   * 查询所有首页应用列表
   */
  async findAll(query: QueryAppDto): Promise<SettingAppIndexEntity[]> {
    const { title, resourceType } = query

    const queryBuilder = this.appRepository
      .createQueryBuilder('app')
      .where('app.isDelete = :isDelete', { isDelete: 0 })

    // 添加筛选条件
    if (title) {
      queryBuilder.andWhere('app.title LIKE :title', { title: `%${title}%` })
    }

    if (resourceType) {
      queryBuilder.andWhere('app.resourceType = :resourceType', { resourceType })
    }

    // 设置默认排序
    queryBuilder.orderBy('app.sort', 'ASC')

    return queryBuilder.getMany()
  }

  /**
   * 查询单个首页应用
   */
  async findOne(id: number) {
    const app = await this.appRepository
      .createQueryBuilder('app')
      .where('app.id = :id', { id })
      .andWhere('app.isDelete = :isDelete', { isDelete: 0 })
      .getOne()

    if (!app) {
      throw new NotFoundException(`记录不存在`)
    }

    return app
  }

  /**
   * 更新首页应用信息
   */
  async update(id: number, updateAppDto: UpdateAppDto) {
    const app = await this.findOne(id)

    return this.appRepository.save({
      ...app,
      ...updateAppDto,
      seriesIds: updateAppDto.seriesIds
        ? updateAppDto.seriesIds.map(([id, type]) => [Number(id), Number(type)])
        : app.seriesIds,
    })
  }

  /**
   * 删除首页应用（逻辑删除）
   */
  async remove(id: number) {
    const app = await this.findOne(id)

    // 逻辑删除
    app.isDelete = 1

    return this.appRepository.save(app)
  }

  /**
   * 获取所有的 book-tag 和 book关联查询的结果
   * - 只查询 tag 的 id (as value), tagName (as label)
   * - 只查询关联 book 的 id, bookName (as label)
   * - 过滤掉已软删除的记录
   */
  async findAllBookTagsWithBooks(): Promise<{ value: number, label: string, children: { value: number, label: string }[] }[]> {
    const rawResults = await this.bookTagRepository
      .createQueryBuilder('tag')
      .select([
        'tag.id AS tag_value', // 从 BookTagEntity 选择 id 并别名为 tag_value
        'tag.tagName AS tag_label', // 从 BookTagEntity 选择 tagName 并别名为 tag_label
        'book.id AS book_id', // 从 BookEntity 选择 id 并别名为 book_id
        'book.bookName AS book_label', // 从 BookEntity 选择 bookName 并别名为 book_label
      ])
      .leftJoin(
        BookEntity,
        'book',
        'book.bookTagId = tag.id AND book.isDelete = :isDeleted', // 关联条件并检查 book 是否软删除
      )
      .where('tag.isDelete = :isDeleted', { isDeleted: 0 }) // 检查 tag 是否软删除
      .orderBy('tag.id') // 保证父级顺序
      .addOrderBy('book.id') // 保证子级顺序 (可选)
      .getRawMany()

    // 手动将扁平的原始结果转换为期望的嵌套结构
    const groupedResults: { [key: number]: { value: number, label: string, children: { value: number, label: string }[] } } = {}

    for (const item of rawResults) {
      const tagValue = Number(item.tag_value)
      if (!groupedResults[tagValue]) {
        groupedResults[tagValue] = {
          value: tagValue,
          label: item.tag_label,
          children: [],
        }
      }
      // 如果存在关联的书籍 (book_id 不为 null)
      if (item.book_id) {
        groupedResults[tagValue].children.push({
          value: Number(item.book_id),
          label: item.book_label,
        })
      }
    }
    return Object.values(groupedResults)
  }

  /**
   * 获取所有的 video-tag 和 movie 关联查询的结果
   * - 只查询 tag 的 id (as value), tagName (as label)
   * - 只查询关联 movie 的 id, videoName (as label)
   * - 过滤掉已软删除的记录
   */
  async findAllVideoTagsWithMovies(): Promise<{ value: number, label: string, children: { value: number, label: string }[] }[]> {
    const rawResults = await this.videoTagRepository
      .createQueryBuilder('tag')
      .select([
        'tag.id AS tag_value', // 从 VideoTagEntity 选择 id 并别名为 tag_value
        'tag.tagName AS tag_label', // 从 VideoTagEntity 选择 tagName 并别名为 tag_label
        'movie.id AS movie_id', // 从 MovieEntity 选择 id 并别名为 movie_id
        'movie.videoName AS movie_label', // 从 MovieEntity 选择 videoName 并别名为 movie_label
      ])
      .leftJoin(
        MovieEntity,
        'movie',
        'movie.videoTagId = tag.id AND movie.isDelete = :isDeleted', // 关联条件并检查 movie 是否软删除
      )
      .where('tag.isDelete = :isDeleted', { isDeleted: 0 }) // 检查 tag 是否软删除
      .orderBy('tag.id')
      .addOrderBy('movie.id')
      .getRawMany()

    const groupedResults: { [key: number]: { value: number, label: string, children: { value: number, label: string }[] } } = {}

    for (const item of rawResults) {
      const tagValue = Number(item.tag_value)
      if (!groupedResults[tagValue]) {
        groupedResults[tagValue] = {
          value: tagValue,
          label: item.tag_label,
          children: [],
        }
      }
      if (item.movie_id) {
        groupedResults[tagValue].children.push({
          value: Number(item.movie_id),
          label: item.movie_label,
        })
      }
    }
    return Object.values(groupedResults)
  }

  /**
   * 批量更新排序
   */
  async updateSort(sortList: { id: number, sort: number }[]) {
    console.log(sortList)

    // 使用事务来确保所有更新要么全部成功，要么全部失败
    return this.appRepository.manager.transaction(async (manager) => {
      const promises = sortList.map(({ id, sort }) =>
        manager.update(
          SettingAppIndexEntity,
          { id },
          { sort },
        ),
      )
      await Promise.all(promises)
      return { message: '更新成功' }
    })
  }
}
